<?
##########################################################################
#		DOCUMENTATION
##########################################################################
# Main class that create a php data-structure of the database. In this way
# we can "cache" the request to database and do them only once in the same
# page (if needed) and make things easier to other modules that must not
# use the database directly.
#
# This class has only the mothods in common to every module that extends it,
# it's suggested to add a method to derived classes if possible.
#
# © LiberLab group, 2011
##########################################################################

class Core {
	# create only one database for every class the is derived from core class
	protected static $database; protected static $cache = array();
	private $queryViews = "SELECT id, title, views FROM books ORDER BY views DESC LIMIT :limit;";
	public function __construct() {
		if (!self::$database){
			require_once("database.php");
			require_once("generalFunctions.php");
			self::$database = new Database();
		}
	}
	
	public function queryCache($query, $parameters = array(), $limit = null, $refreshTime = 2){
		# know if the query has been already submitted or not
		$cache = self::$cache;
		$query = trim($query);
		foreach($parameters as $key => $parameter){
			$query = preg_replace("/:{$key}/", "\"$parameter\"", $query);
		}
		$query = preg_replace("/ *?LIMIT +?\"\d+?\"/", "", $query);
		if (isset($cache[$query])){
			# avoid multiple access to the hashMap and save time
			$cacheArray = $cache[$query]; 
			# if we are in the refreshLimits
			if ((mytimestamp($cacheArray["timestamp"]) < $refreshTime) and 
				# the query has a query limit? no? ok. Yes? Uhm, is the limit set in the query cached? Yes? it's <= of the limit given? Ok
				(!isset($cacheArray["limit"]) or (isset($cacheArray["limit"]) and $limit != null and $cacheArray["limit"] >= $limit))){
				return array(true, $query); 
			}
		}
		return array(false, $query); # hit miss
	} 
	
	public function cacheCheck($query, $fresh){
		# check if a query has already been submitted
		$cache = self::$cache;
		$res = $this->queryCache($query);
		$queryCacheRes = $res[0]; $queryCache = $res[1];
		if (!$fresh and $queryCacheRes){		
			return array($cache[$queryCache]["data"], $queryCache);
		}else{
			return array(null, $queryCache);
		}
	}
	
	public function cacheInsert($data, $queryCache, $limit = null){
		# insert a new query in the cache with the results
		$cache = self::$cache;
		if ($limit != null){
			$cache[$queryCache] = array("timestamp" => mytimestamp(), "data" => $data);
		}else{
			$cache[$queryCache] = array("timestamp" => mytimestamp(), "data" => $data, "limit" => $limit);
		}
		self::$cache = $cache;
	}
	
	public function orderByAddon($query, $orderBy, $desc = false){
		# add to the query the ORDER BY correctly
		$database = self::$database;
		if ($orderBy and $database->sanitize($orderBy)){
			if ($desc){
				$query = $query . " ORDER BY $orderBy DESC";
			}else{
				$query = $query . " ORDER BY $orderBy";
			}	
		}
		return $query;
	}
	
	public function limitAddon($query, $limit = 20, $startId = 0){
		# add to the query the LIMIT correctly
		$database = self::$database;
		if ($startId and $limit and $database->sanitize(array($startId, $limit))){
			$query = $query . " LIMIT $startId, $limit";
		}else if($limit and $database->sanitize($limit)){
			$query = $query . " LIMIT $limit";
		}
		return $query;
	}
	
	public function getId($whereCheck, $id="id", $from = "books", $whereClause = "title", $fresh = false){
		# get the id from a given table
		$database = self::$database;
		$cache = self::$cache;
		$whereCheck = trim($whereCheck);
		$query = "SELECT $id FROM $from WHERE $whereClause = :whereCheck";
		$res = $this->queryCache($query, $parameters = array("whereCheck" => $whereCheck));
		$queryCacheRes = $res[0]; $queryCache = $res[1];
		
		if ($fresh or !$queryCacheRes){			
			if ($database->sanitize(array($id, $from, $whereClause))){
				$stpdo = $database->getStpdo($query);

				$stpdo->bindParam(':whereCheck', $whereCheck, PDO::PARAM_STR); 
				$stpdo->bindColumn(1, $id);
				$stpdo->execute(); 

				$row = $stpdo->fetch(PDO::FETCH_OBJ);
				if ($row){
					$this->cacheInsert($row->id, $queryCache);
					return $row->id;
				}
			}
			return null;
		}
		return $cache[$queryCache]["data"];
	}

	public function __destruct() {
	}
};

?>
